//
//  opencvWrapper.m
//  Entrance
//
//  Created by chunhuiLai on 2018/1/16.
//  Copyright © 2018年 chunhuiLai. All rights reserved.
//

#import "OpenCVWrapper.h"
#import <opencv2/opencv.hpp>
#import <opencv2/imgproc/types_c.h>
#import <opencv2/imgcodecs/ios.h>
#import <TesseractOCR/TesseractOCR.h>


@implementation OpenCVWrapper

+ (instancetype)shared {
    static OpenCVWrapper *wrapper = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        wrapper = [[OpenCVWrapper alloc] init];
    });
    return wrapper;
}

- (NSString *)recognizeCardWithImage:(UIImage *)cardImage {
    //扫描身份证图片，并进行预处理，定位号码区域图片并返回
    UIImage *numberImage = [self opencvScanCard: cardImage];
    if (numberImage == nil) {
        return nil;
    }
    
    //利用TesseractOCR识别文字
    return [self tesseractRecognizeWithImage: numberImage];
}


//- (void)recognizeCardWithImage:(UIImage *)cardImage completed:(CompletedBlock)completed {
//    //扫描身份证图片，并进行预处理，定位号码区域图片并返回
//    UIImage *numberImage = [self opencvScanCard:cardImage];
//    if (numberImage == nil) {
//        completed(nil);
//    }
//    //利用TesseractOCR识别文字
//    [self tesseractRecognizeImage:numberImage completed:^(NSString *numbaerText) {
//        completed(numbaerText);
//    }];
//}


//扫描身份证图片，并进行预处理，定位号码区域图片并返回
- (UIImage *)opencvScanCard:(UIImage *)image {
    
    //将UIImage转换成Mat
    cv::Mat resultImage;
    UIImageToMat(image, resultImage);
    //转为灰度图
    cvtColor(resultImage, resultImage, cv::COLOR_BGR2GRAY);
    //利用阈值二值化
    cv::threshold(resultImage, resultImage, 100, 255, CV_THRESH_BINARY);

    //腐蚀，填充（腐蚀是让黑色点变大）
    cv::Mat erodeElement = getStructuringElement(cv::MORPH_RECT, cv::Size(34,34));
    cv::erode(resultImage, resultImage, erodeElement);
    
   // return  MatToUIImage(resultImage);
    //轮廊检测
    std::vector<std::vector<cv::Point>> contours;//定义一个容器来存储所有检测到的轮廊
    cv::findContours(resultImage, contours, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
    //cv::drawContours(resultImage, contours, -1, cv::Scalar(255),4);
    //取出身份证号码区域
    std::vector<cv::Rect> rects;
    cv::Rect numberRect = cv::Rect(0,0,0,0);
    std::vector<std::vector<cv::Point>>::const_iterator itContours = contours.begin();
    for ( ; itContours != contours.end(); ++itContours) {
        cv::Rect rect = cv::boundingRect(*itContours);
        rects.push_back(rect);
        //算法原理
        if (rect.width > numberRect.width && rect.width > rect.height * 5) {
            numberRect = rect;
        }
    }
    //身份证号码定位失败
    if (numberRect.width == 0 || numberRect.height == 0) {
        return nil;
    }
    //定位成功成功，去原图截取身份证号码区域，并转换成灰度图、进行二值化处理
    cv::Mat matImage;
    UIImageToMat(image, matImage);
    resultImage = matImage(numberRect);
    cvtColor(resultImage, resultImage, cv::COLOR_BGR2GRAY);
    cv::threshold(resultImage, resultImage, 80, 255, CV_THRESH_BINARY);
    //将Mat转换成UIImage
    UIImage *numberImage = MatToUIImage(resultImage);
    return numberImage;
}

////利用TesseractOCR识别文字
//- (void)tesseractRecognizeImage:(UIImage *)image completed:(CompletedBlock)completed {
//
//    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
//        G8Tesseract *tesseract = [[G8Tesseract alloc] initWithLanguage:@"eng"];
//        tesseract.image = [image g8_blackAndWhite];
//        tesseract.image = image;
//        // Start the recognition
//        [tesseract recognize];
//        //执行回调
//        completed(tesseract.recognizedText);
//    });
//}


//利用TesseractOCR识别文字
- (NSString *)tesseractRecognizeWithImage:(UIImage *)image {
    
    G8Tesseract *tesseract = [[G8Tesseract alloc] initWithLanguage:@"eng"];
    tesseract.image = [image g8_blackAndWhite];
    tesseract.pageSegmentationMode = G8PageSegmentationModeAuto;
   
    [tesseract recognize];

    return tesseract.recognizedText;

}

@end
